package com.unitechs.trap.excel.webapi.service.impl;

import com.unitechs.trap.common.pojo.config.ExConfiguration;
import com.unitechs.trap.common.pojo.trap.entity.AllData;
import com.unitechs.trap.common.pojo.trap.entity.UpDown;
import com.unitechs.trap.excel.service.ICreatAlarmCodeService;
import com.unitechs.trap.excel.webapi.mapper.CoInfoMapper;
import com.unitechs.trap.excel.webapi.mapper.UpDownMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@DubboService
public class CreatAlarmCodeServiceImpl implements ICreatAlarmCodeService {

    @Autowired
    private CoInfoMapper mapper;

    @Autowired
    private UpDownMapper upDownMapper;


    public List<AllData> CreatAlarmCode(List<AllData> list, String url, String coName, String version) {
        switch (version) {
            case "A":
                list = creatAlarmCode_A(list, coName);
                break;
            case "B":
                list = creatAlarmCode_B(list, coName, url);
                break;
            case "C":
                list = creatAlarmCode_C(list, coName);
                break;
            case "D":
                list = creatAlarmCode_D(list, coName);
                break;

        }
        return list;
    }

    /**
     * 两字符串相似度匹配
     * (最长的字符串长度-重复的字符数量)/最长的的字符串长度
     * 值越接近1，两字符串越相似
     * @param str1
     * @param str2
     * @return
     */
    private double calculateStringSimilarity(String str1, String str2) {
        int len1 = str1.length();
        int len2 = str2.length();
        int maxLength = Math.max(len1, len2);
        int minLength = Math.min(len1, len2);
        int distance = 0;

        for (int i = 0; i < minLength; i++) {
            if (str1.charAt(i) != str2.charAt(i)) {
                distance++;
            }
        }

        distance += maxLength - minLength;

        return (double)(maxLength - distance) / maxLength;
    }

    /**
     * D模板
     * 含变量oid，有恢复和告警的字段
     * 难点：无法判断谁是谁的恢复，谁又是谁的告警
     * 解决方案:使用相似律匹配，找到除自身以外和自己最相似的一条数据
     * @param list
     * @param coName
     * @return
     */
    private List<AllData> creatAlarmCode_D(List<AllData> list, String coName) {
        //*找到所有的告警，生成alarmtype_code并设置alarm_status
        for (AllData allData : list) {
            if (allData.getUpDown().equals("恢复")) {continue;}
                allData.setAlarmtypeCode(allData.getAlarmclassCode() + mapper.getCoCodeByCoName(coName));
                mapper.increaseCoCode(coName);
                allData.setAllIndex(1);

        }

        //*找到所有恢复
        for (AllData allData:list) {
            if (!allData.getUpDown().equals("恢复")){continue;}
            String allDataTrapTypeCode = allData.getTrapTypeCode();
            AllData mostSimilarData = new AllData();
            double highestSimilarity = 0.0;
            //*寻找与此恢复对应的告警，并将对应告警的alarmtype_code赋值给此恢复
            for (AllData data : list) {
                //遍历时跳过自身
                if (data.getTrapTypeCode().equals(allDataTrapTypeCode)||data.getUpDown().equals("恢复")) {
                    continue;
                }
                //相似律匹配，找到对应的恢复
                double similarity = calculateStringSimilarity(allDataTrapTypeCode, data.getTrapTypeCode());
                if (similarity > highestSimilarity) {
                    highestSimilarity = similarity;
                    mostSimilarData=data;
                }
            }
            allData.setAllIndex(0);
            //*赋值alarmtype_code
            allData.setAlarmtypeCode(mostSimilarData.getAlarmtypeCode());
        }

        return list;
    }

    /**
     * B模板
     * 不含变量oid，但是给出了告警对应恢复的oid
     * 难点:数据不在同一张表中
     *
     * @param list
     * @param coName
     * @param url
     * @return
     */
    private List<AllData> creatAlarmCode_B(List<AllData> list, String coName, String url) {


        try {
            HSSFWorkbook xssfWorkbook = new HSSFWorkbook(new FileInputStream(url));
            //读取第2个工作表
            HSSFSheet sheet = xssfWorkbook.getSheetAt(1);
            //获取最后一行的num，即总行数。此处从0开始
            int maxRow = sheet.getLastRowNum();
            Map<String, String> upTrapOids = new HashMap<>();

            for (AllData allData : list) {//找到所有一对的告警和恢复
                for (int row = 1; row <= maxRow; row++) {
                    if (!(sheet.getRow(row).getCell(ExConfiguration.B_ExConfiguration.B_TRAP_OID_UP_CELL_TWO) == null
                            || sheet.getRow(row).getCell(ExConfiguration.B_ExConfiguration.B_TRAP_OID_UP_CELL_TWO).toString().equals(""))
                            && allData.getTrapOid().equals(sheet.getRow(row).getCell(ExConfiguration.B_ExConfiguration.B_TRAP_OID_UP_CELL_TWO).toString())) {
                        String key = sheet.getRow(row).getCell(ExConfiguration.B_ExConfiguration.B_TRAP_OID_CELL_TWO).toString();
                        String value = sheet.getRow(row).getCell(ExConfiguration.B_ExConfiguration.B_TRAP_OID_UP_CELL_TWO).toString();
                        allData.setAllIndex(0);
                        upTrapOids.put(key, value);
                    }

                }
            }


            for (AllData allData : list) {//为所有告警的AlarmtypeCode赋值
                if (allData.getAllIndex() == null || allData.getAllIndex().equals("")) {
                    allData.setAlarmtypeCode(allData.getAlarmclassCode() + mapper.getCoCodeByCoName(coName));
                    mapper.increaseCoCode(coName);
                    allData.setAllIndex(1);
                }
            }


            for (AllData allData : list) {
                for (Map.Entry<String, String> entry : upTrapOids.entrySet()) {
                    if (allData.getTrapOid().equals(entry.getValue())) {//如果此条数据是恢复
                        for (AllData data : list) {//找到对应告警的AlarmtypeCode
                            if (data.getTrapOid().equals(entry.getKey())) {
                                allData.setAlarmtypeCode(data.getAlarmtypeCode());
                                break;
                            }
                        }
                        break;
                    }
                }
            }


        } catch (IOException e) {
            e.printStackTrace();
        }

        for (AllData allData : list) {
            if (allData.getAlarmtypeCode() == null || allData.getAlarmtypeCode().equals("")) {
                allData.setAlarmtypeCode("异常数据无法处理");
            }
        }
        return list;
    }

    /**
     * 根据【数据库字典】生成【alarmcode】
     * 并判断恢复还是告警
     *
     * @param list
     * @param coName
     * @return
     */
    private List<AllData> creatAlarmCode_A(List<AllData> list, String coName) {
        //处理Code
        for (AllData allDataUp : list) {//遍历所有数据
            int lastCode = mapper.getCoCodeByCoName(coName);
            List<UpDown> upDowns = upDownMapper.listUpDown(coName);//获取所有结尾键值对
            String strUp = allDataUp.getTrapTypeCode().toLowerCase();//up的标题
            if (allDataUp.getAlarmtypeCode() == null) {
                allDataUp.setAlarmtypeCode(allDataUp.getAlarmclassCode() + lastCode);//生成id
                mapper.increaseCoCode(coName);
            }
            for (UpDown upDown : upDowns) {
                if (!strUp.endsWith(upDown.getTrapUp().toLowerCase())) {
                    continue;
                }//如果Up结尾不吻合字典 跳过upDown
                if (strUp.length() < upDown.getTrapUp().toLowerCase().length()) {
                    continue;
                }//如果截取字典up后长度小于0 跳过upDown
                String strSubUp = strUp.substring(0, strUp.length() - upDown.getTrapUp().toLowerCase().length());//去掉up结尾
                List<UpDown> downs = upDownMapper.listUpDownByEnd(upDown.getTrapUp().toLowerCase(), coName);//根据up结尾获取字典中down的结尾集
                for (AllData allDataDown : list) {
                    if ((allDataDown.getTrapOid().length() - allDataUp.getTrapOid().length()) >= 2
                            || (allDataDown.getTrapOid().length() - allDataUp.getTrapOid().length()) <= -2
                    ) {
                        continue;
                    }
                    if (allDataUp.equals(allDataDown)) {
                        continue;
                    }//如果是同一条数据 跳过allDataDown
                    String strDown = allDataDown.getTrapTypeCode().toLowerCase();//down的标题
                    for (UpDown down : downs) {
                        if (strDown.length() < down.getTrapDown().toLowerCase().length()) {
                            continue;
                        }//如果截取字典down后长度小于0 跳过down
                        String strSubDown = strDown.substring(0, strDown.length() - down.getTrapDown().toLowerCase().length());//去除后缀的down
                        if (!(strDown.endsWith(down.getTrapDown().toLowerCase()) || strSubUp.equals(strDown))) {
                            continue;
                        }//如果down结尾不吻合字典 跳过down
                        if (strSubUp.equals(strSubDown) || strSubUp.equals(strDown)) {//如果（去除后缀的down/down）等于去除后缀的up 表示匹配成功
                            allDataUp.setAllIndex(0);//匹配成功，此allDataUp为恢复
                            if (allDataDown.getAlarmtypeCode() == null) {//如果此down没有alarm_type_code,将up的code给down
                                allDataDown.setAlarmtypeCode(allDataUp.getAlarmtypeCode());
                            } else {//如果此down有alarm_type_code,将down的code给up，并恢复id为上次id
                                allDataUp.setAlarmtypeCode(allDataDown.getAlarmtypeCode());
                                mapper.recoverCoCode(coName, lastCode);//恢复数据库code
                            }
                            break;//匹配到数据跳出循环
                        }

                        if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                            break;
                        }
                    }
                    if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                        break;
                    }
                }
                if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                    break;
                }
            }

            if (allDataUp.getAllIndex() == null) {
                allDataUp.setAllIndex(1);
            }
        }

        return list;
    }

    /**
     * 根据【数据库字典】生成【alarmcode】
     * 并判断恢复还是告警
     *
     * @param list
     * @param coName
     * @return
     */
    private List<AllData> creatAlarmCode_C(List<AllData> list, String coName) {
        //处理Code
        for (AllData allDataUp : list) {//遍历所有数据
            int lastCode = mapper.getCoCodeByCoName(coName);
            List<UpDown> upDowns = upDownMapper.listUpDown(coName);//获取所有结尾键值对
            String strUp = allDataUp.getTrapTypeCode().toLowerCase();//up的标题
            if (allDataUp.getAlarmtypeCode() == null) {
                allDataUp.setAlarmtypeCode(allDataUp.getAlarmclassCode() + lastCode);//生成id
                mapper.increaseCoCode(coName);
            }
            for (UpDown upDown : upDowns) {
                if (!strUp.endsWith(upDown.getTrapUp().toLowerCase())) {
                    continue;
                }//如果Up结尾不吻合字典 跳过upDown
                if (strUp.length() < upDown.getTrapUp().toLowerCase().length()) {
                    continue;
                }//如果截取字典up后长度小于0 跳过upDown
                String strSubUp = strUp.substring(0, strUp.length() - upDown.getTrapUp().toLowerCase().length());//去掉up结尾
                List<UpDown> downs = upDownMapper.listUpDownByEnd(upDown.getTrapUp().toLowerCase(), coName);//根据up结尾获取字典中down的结尾集
                for (AllData allDataDown : list) {
                    if (allDataUp.equals(allDataDown)) {
                        continue;
                    }//如果是同一条数据 跳过allDataDown
                    String strDown = allDataDown.getTrapTypeCode().toLowerCase();//down的标题
                    for (UpDown down : downs) {
                        if (strDown.length() < down.getTrapDown().toLowerCase().length()) {
                            continue;
                        }//如果截取字典down后长度小于0 跳过down
                        String strSubDown = strDown.substring(0, strDown.length() - down.getTrapDown().toLowerCase().length());//去除后缀的down
                        if (!(strDown.endsWith(down.getTrapDown()) || strSubUp.equals(strDown))) {
                            continue;
                        }//如果down结尾不吻合字典 跳过down
                        if (strSubUp.equals(strSubDown) || strSubUp.equals(strDown)) {//如果（去除后缀的down/down）等于去除后缀的up 表示匹配成功
                            allDataUp.setAllIndex(0);//匹配成功，此allDataUp为恢复
                            if (allDataDown.getAlarmtypeCode() == null) {//如果此down没有alarm_type_code,将up的code给down
                                allDataDown.setAlarmtypeCode(allDataUp.getAlarmtypeCode());
                            } else {//如果此down有alarm_type_code,将down的code给up，并恢复id为上次id
                                allDataUp.setAlarmtypeCode(allDataDown.getAlarmtypeCode());
                                mapper.recoverCoCode(coName, lastCode);//恢复数据库code
                            }
                            break;//匹配到数据跳出循环
                        }

                        if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                            break;
                        }
                    }
                    if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                        break;
                    }
                }
                if (allDataUp.getAllIndex() != null) {//匹配到数据跳出循环
                    break;
                }
            }

            if (allDataUp.getAllIndex() == null) {
                allDataUp.setAllIndex(1);
            }
        }

        return list;
    }
}
